﻿#region License
/* ---------------------------------------------------------------- *
 *
 * This file is part of the API Concepts Framework
 * http://apiconceptsframework.codeplex.com
 *
 * Copyright (C) 2014 eva Kühn, Thomas Scheller, Vienna University of Technology
 * http://www.complang.tuwien.ac.at/eva
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see http://www.gnu.org/licenses/
 *
 * ---------------------------------------------------------------- */
#endregion

using System.Runtime.CompilerServices;
using ApiConceptsFramework.Contract;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace ApiConceptsFramework
{
	public static class ConsolePrintingExtensions
	{
		public static string ToPrintableString(this MeasurableTarget target)
		{
			var typeName = target.Type.ToPrintableString();
			if (target.Member == null)
				return typeName;
			if (target.Member is ConstructorInfo)
				return ((ConstructorInfo)target.Member).ToPrintableString(typeName);
			if (target.Member is MethodInfo)
				return ((MethodInfo)target.Member).ToPrintableString(typeName) + (!target.ReturnedValueIsUsed ? " (return value not used)" : "");
			if (target.Member is FieldInfo)
				return ((FieldInfo)target.Member).ToPrintableString(typeName);
			if (target.Member is PropertyInfo)
				return ((PropertyInfo)target.Member).ToPrintableString(typeName);
			throw new ArgumentException("target.Member Type " + target.Member.GetType().Name + " is unknown", "target");
		}

		public static string ToPrintableString(this Type type)
		{
			if (type.IsGenericType)
				return type.Name.Substring(0, type.Name.Length - 2) + "<" + string.Join(",", type.GetGenericArguments().Select(t => ""/*t.ToPrintableString()*/)) + ">";
			return type.Name;
		}

		public static string ToPrintableString(this ConstructorInfo info, string typename)
		{
			var str = typename + "(" + string.Join(",", info.GetParameters().Select(p => p.ToPrintableString())) + ")";
			var declaringTypeIsAttribute = info.DeclaringType.IsSubclassOf(typeof(Attribute));
			return declaringTypeIsAttribute ? ("[" + str + "]") : ("new " + str);
		}

		public static string ToPrintableString(this MethodInfo info, string typename)
		{
			//bool isVoid = info.ReturnType == typeof(void);
			bool isExtension = info.IsDefined(typeof(ExtensionAttribute), false);
			return /*(isVoid ? "void " : (info.ReturnType.ToPrintableString() + " ")) +*/ typename + "." + info.Name
				+ (info.IsGenericMethod ? ("<" + string.Join(",", info.GetGenericArguments().Select(p => "")) + ">") : "")
				+ "(" + string.Join(",", info.GetParameters().Skip(isExtension ? 1: 0).Select(p => p.ToPrintableString())) + ")";
		}

		public static string ToPrintableString(this PropertyInfo info, string typename)
		{
			return /*info.PropertyType.ToPrintableString() + " " +*/ typename + "." + info.Name + (info.GetIndexParameters().Length > 0 ? " (indexer property)" : ""); 
		}

		public static string ToPrintableString(this FieldInfo info, string typename)
		{
			return /*info.FieldType.ToPrintableString() + " " +*/ typename + "." + info.Name;
		}

		public static string ToPrintableString(this ParameterInfo info)
		{
			return info.ParameterType.ToPrintableString(); // + " " + info.Name;
		}
	}
}
